package com.kinroy.briefreport.service.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kinroy.briefreport.dto.ProjectDto;
import com.kinroy.briefreport.dto.ProjectInfoDto;
import com.kinroy.briefreport.dto.Result;
import com.kinroy.briefreport.entity.*;
import com.kinroy.briefreport.enums.project.ProjectStatus;
import com.kinroy.briefreport.mapper.HandOverNodeMapper;
import com.kinroy.briefreport.mapper.ProjectMapper;
import com.kinroy.briefreport.mapper.TaskMapper;
import com.kinroy.briefreport.mapper.UserMapper;
import com.kinroy.briefreport.service.IProjectService;
import com.kinroy.briefreport.service.IUserService;
import com.kinroy.briefreport.utils.UUIDJudgmentTool;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TaskMapper taskMapper;


    @Autowired
    private HandOverNodeMapper handOverNodeMapper;

    /**
     * 通过projectId来获取对应的项目名称
     *
     * @param projectId
     * @return
     */
    @Override
    public Result getProjectNameById(String projectId) {
        LambdaQueryWrapper<Project> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(projectId != null && projectId != "", Project::getProjectId, projectId);
        Project one = getOne(lambdaQueryWrapper);
        if (one != null) {
            return Result.ok(one.getProjectName());
        }
        return Result.fail("解析项目名称失败！");
    }

    /**
     * 通过项目id获取到当前项目的组员id的集合
     *
     * @param projectId
     * @return
     */
    @Override
    public List<Long> getUserListByProjectId(String projectId) {
        if (StrUtil.isBlank(projectId)) {
            return null;
        }
        List<Long> allUserInProjectInc = projectMapper.getAllUserInProjectInc(projectId);
        return allUserInProjectInc;
    }

    /**
     * 通过userId获取到当前用户管理的项目
     *
     * @param userId
     * @return
     */
    @Override
    public Result getMyManagerProjects(Long userId) {
        //1.判断当前用户是否为项目组长及以上
        User selectUser = new User();
        selectUser.setUid(userId);
        int countPermissions = userMapper.verifyPermissions(selectUser);

        if (countPermissions == 0) {
            return Result.fail("当前用户没有权限！");
        }
        //2.获取当前用户所管理的项目
        List<Project> userManagerProjectList = null;
        try {
            userManagerProjectList = projectMapper.getUserManagerProjectList(userId);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.ok(null);
        }
        return Result.ok(userManagerProjectList);
    }

    /**
     * 通过项目id查询到项目实体，然后封装成dto返回
     *
     * @param projectId
     * @return
     */
    @Override
    public Result getProjectInfoById(String projectId) {
        ProjectInfoDto projectInfoDto = new ProjectInfoDto();
        LambdaQueryWrapper<Project> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(projectId != null && projectId != "", Project::getProjectId, projectId);
        Project one = getOne(wrapper);
        BeanUtil.copyProperties(one, projectInfoDto);
        //解析项目中的项目创建人id 和 项目组长id 已经项目状态
        String createUserName = userMapper.getUserInfoNameByUserId(one.getCreateUserId());
        projectInfoDto.setCreateUserName(createUserName);
        String projectLeaderName = userMapper.getUserInfoNameByUserId(one.getProjectLeaderId());
        projectInfoDto.setProjectLeaderName(projectLeaderName);
        switch (one.getProjectStatus()) {
            case 0:
                projectInfoDto.setProjectStatusName("未开始");
                break;
            case 1:
                projectInfoDto.setProjectStatusName("进行中");
                break;
            case 2:
                projectInfoDto.setProjectStatusName("已完成");
                break;
        }
        return Result.ok(projectInfoDto);
    }

    /**
     * 向projectId对应的项目添加组员
     *
     * @param projectId
     * @param addUsersIds
     * @return
     */
    @Override
    @Transactional
    public Result addProjectMembers(String projectId, List<Long> addUsersIds) {
        //遍历需要添加入项目的员工ids
        for (int i = 0; i < addUsersIds.size(); i++) {
            Long userId = addUsersIds.get(i);
            projectMapper.addProjectMember(userId, projectId);
        }
        return Result.ok();
    }

    /**
     * projectId对应的项目删除组员
     *
     * @param projectId
     * @param userId
     * @return
     */
    @Override
    public Result removeFormProject(String projectId, Long userId) {
        Boolean aBoolean = projectMapper.removeFormProject(userId, projectId);
        if (aBoolean) {
            return Result.ok();
        }
        return Result.fail("删除成员失败！");
    }


    /**
     * 按条件分页获取项目表格数据
     *
     * @param currentPage
     * @param pageSize
     * @param selectValue
     * @param projectStatusSelectValue
     * @return
     */
    @Override
    public Result getProjectConditionalQueryByPage(Long currentPage, Long pageSize, String selectValue, Integer projectStatusSelectValue) {
        LambdaQueryWrapper<Project> wrapper = new LambdaQueryWrapper<>();
        if (selectValue != null && selectValue != "") {
            //走按projectId或者projectName进行查询的逻辑
        }

        if (projectStatusSelectValue != 3) {
            //当前端传来的projectStatus!=3的时候表示不查询所有项目
            wrapper.eq(Project::getProjectStatus, projectStatusSelectValue);
        }
        //2.分页查询
        wrapper.orderByDesc(Project::getCreateTime);
        Page<Project> notePage = new Page<>(currentPage, pageSize);
        Page<Project> page = this.page(notePage, wrapper);

        //3.返回前端数据： 1.当前页面数据  2.数据总页数
        List<Project> records = page.getRecords();
        //对获取到的projectList进行处理

        List<ProjectInfoDto> projectDtoList = new ArrayList<>();
        for (Project project : records) {
            //转换成Dto返回前端
            String projectId = project.getProjectId();
            ProjectInfoDto projectInfoDto = new ProjectInfoDto();
            LambdaQueryWrapper<Project> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(projectId != null && projectId != "", Project::getProjectId, projectId);
            Project one = getOne(lambdaQueryWrapper);
            BeanUtil.copyProperties(one, projectInfoDto);
            //解析项目中的项目创建人id 和 项目组长id 已经项目状态
            String createUserName = userMapper.getUserInfoNameByUserId(one.getCreateUserId());
            projectInfoDto.setCreateUserName(createUserName);
            String projectLeaderName = userMapper.getUserInfoNameByUserId(one.getProjectLeaderId());
            projectInfoDto.setProjectLeaderName(projectLeaderName);
            switch (one.getProjectStatus()) {
                case 0:
                    projectInfoDto.setProjectStatusName("未开始");
                    break;
                case 1:
                    projectInfoDto.setProjectStatusName("进行中");
                    break;
                case 2:
                    projectInfoDto.setProjectStatusName("已完成");
                    break;
            }
            //加入到projectDtoList
            projectDtoList.add(projectInfoDto);
        }
        long total = page.getTotal();
        Map<String, Object> reslut = new HashMap<>();
        reslut.put("pageData", projectDtoList);
        reslut.put("totalData", total);
        return Result.ok(reslut);

    }

    /**
     * 删除项目及其相关信息（项目中的任务，项目中的组员关系，项目中任务的流转节点信息）
     * 操作tb_project,tb_task,project_user_relation 三张表
     *
     * @param projectId
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public Result delProject(String projectId, Long userId) {
        //1.判断当前用户是否有权限进行项目删除操作
        LambdaQueryWrapper<Project> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Project::getProjectId, projectId);
        Project one = getOne(wrapper);
        if (!one.getCreateUserId().equals(userId)) {
            return Result.fail("您没有删除当前项目的权限！");
        }
        //1.查询出当前项目的所有的task的id
        List<String> taskIdListByProjectId = taskMapper.getTaskIdListByProjectId(projectId);
        //kinroy 2024.2.22 修复删除空项目(项目中没有任务)时爆出的异常
        if (taskIdListByProjectId.size()==0){
            Boolean aBoolean = projectMapper.delProjectMemberByProjectId(projectId);
            //删除project表中的project数据
            int deleteById = projectMapper.deleteById(projectId);
            return Result.ok();
        }

        //2.根据taskId去删除对应handOverNode数据
        LambdaQueryWrapper<HandOverNode> handOverNodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        handOverNodeLambdaQueryWrapper.in(HandOverNode::getTaskId, taskIdListByProjectId);


        int delete = handOverNodeMapper.delete(handOverNodeLambdaQueryWrapper);

        //3.根据taskId去删除对应的task
        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.in(Task::getTaskId, taskIdListByProjectId);
        int delete1 = taskMapper.delete(taskLambdaQueryWrapper);

        //4.根据project_id去删除对应的用户和项目的绑定数据
        Boolean aBoolean = projectMapper.delProjectMemberByProjectId(projectId);

        //删除project表中的project数据
        int deleteById = projectMapper.deleteById(projectId);

        /*//5.删除对应的project信息
        int delete2 = projectMapper.delete(wrapper);*/
        if (delete == 0 || delete1 == 0  || aBoolean == false||deleteById ==0) {
            return Result.fail("删除失败！");
        }
        return Result.ok();
    }


    /**
     * 修改项目信息，只能修改项目的状态和项目名称
     *
     * @param projectInfoDto
     * @return
     */
    @Override
    public Result editProjectInfo(ProjectInfoDto projectInfoDto) {
        //1.将dto转换成project实体，方便修改数据库信息
        Project project = new Project();
        BeanUtils.copyProperties(projectInfoDto, project);
        //2.判断修改的状态，做对应的更改
        switch (project.getProjectStatus()) {
            case 0:
                //未开始，若当前项目存在有未完成的task，则无法修改成未开始状态
                List<String> taskIdListByProjectId = taskMapper.getTaskIdListByProjectId(projectInfoDto.getProjectId());
                if (taskIdListByProjectId.size() > 0) {
                    return Result.fail("当前项目还有未完成的任务，无法修改成未开始状态！");
                }
                //设置为未完成
                project.setProjectStatus(0);
                project.setCompletionTime(null);
                break;
            case 1:
                //进行中
                project.setProjectStatus(1);
                break;
            case 2:
                //已完成，当前项目的所有task都已经完成，才能设置成为已完成状态
                Integer countUnCompleteNumInProject = taskMapper.countUnCompleteNumInProject(project.getProjectId());
                if (countUnCompleteNumInProject > 0) {
                    return Result.fail("当前项目还有任务未完成，无法修改为已完成状态！");
                }
                project.setProjectStatus(2);
                LocalDateTime now = LocalDateTime.now();
                project.setCompletionTime(now);
                break;
            default:
                break;
        }
        boolean updateById = updateById(project);
        if (updateById) {
            return Result.ok();
        }
        return Result.fail("修改失败！");
    }

    /**
     * 根据projectId指定当前项目的项目负责人
     *
     * @param projectInfoDto
     * @param userId
     * @param projectLeaderId
     * @return
     */
    @Override
    public Result projectAssignment(ProjectInfoDto projectInfoDto, Long userId, Long projectLeaderId) {
        //1.校验是否具有指派权限
        Long createUserId = projectInfoDto.getCreateUserId();
        if (!createUserId.equals(userId)) {
            //当前用户不是当前项目的创建者，则不能指派当前项目
            return Result.fail("指派失败，您不是当前项目创建者！");
        }
        //2.属性拷贝后修改tb_project表
        Project project = new Project();
        BeanUtils.copyProperties(projectInfoDto, project);
        project.setProjectLeaderId(projectLeaderId);

        //2024.3.18 kinroy 指派项目时，判断当前是否是未开始，如果是未开始，则修改对应的状态
        int projectStatus = project.getProjectStatus();
        if (projectStatus==0){
            project.setProjectStatus(ProjectStatus.PROGRESS.getCode());
        }

        boolean updateById = updateById(project);
        if (updateById) {
            return Result.ok();
        }
        return Result.fail("项目指派失败！");
    }

    /**
     * 通过projectId或者projectName进行条件查询或者模糊查询
     * @param selectValue
     * @return
     */
    @Override
    public Result selectProjectByIdOrName(String selectValue) {
        LambdaQueryWrapper<Project> wrapper=new LambdaQueryWrapper<>();
        //判断当前查询条件是projectId还是projectName
        boolean flag = UUIDJudgmentTool.uuidMatch(selectValue);

        if (flag){
            //是通过id查询
            wrapper.eq(Project::getProjectId,selectValue);
        }else {
            wrapper.like(Project::getProjectName,selectValue);
        }
        List<Project> projectList = list(wrapper);
        //对获取到的projectList进行处理

        List<ProjectInfoDto> projectDtoList = new ArrayList<>();
        for (Project project : projectList) {
            //转换成Dto返回前端
            String projectId = project.getProjectId();
            ProjectInfoDto projectInfoDto = new ProjectInfoDto();
            LambdaQueryWrapper<Project> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(projectId != null && projectId != "", Project::getProjectId, projectId);
            Project one = getOne(lambdaQueryWrapper);
            BeanUtil.copyProperties(one, projectInfoDto);
            //解析项目中的项目创建人id 和 项目组长id 已经项目状态
            String createUserName = userMapper.getUserInfoNameByUserId(one.getCreateUserId());
            projectInfoDto.setCreateUserName(createUserName);
            String projectLeaderName = userMapper.getUserInfoNameByUserId(one.getProjectLeaderId());
            projectInfoDto.setProjectLeaderName(projectLeaderName);
            switch (one.getProjectStatus()) {
                case 0:
                    projectInfoDto.setProjectStatusName("未开始");
                    break;
                case 1:
                    projectInfoDto.setProjectStatusName("进行中");
                    break;
                case 2:
                    projectInfoDto.setProjectStatusName("已完成");
                    break;
            }
            //加入到projectDtoList
            projectDtoList.add(projectInfoDto);
        }

        return Result.ok(projectDtoList);
    }

    /**
     * 新增项目功能
     * 需要校验新增项目的操作用户是否是部门管理员
     * @param project
     * @param userId
     * @return
     */
    @Override
    public Result addProject(Project project, Long userId) {
        //1.校验当前用户是否是部门管理员
        User user=new User();
        user.setUid(userId);
        /*int reslutNum = userMapper.verifyPermissions(user);*/
        int userRoles = userMapper.getUserRoles(userId);
        if (userRoles!=1){
            //不是部门领导不能进行项目创建
            return Result.fail("当前用户没有权限新增项目");
        }
        Long projectLeaderId = project.getProjectLeaderId();
        project.setProjectStatus(ProjectStatus.UNPROGRESS.getCode());

        //存入db中
        boolean save = this.save(project);
        if (save){
            return Result.ok();
        }
        return Result.fail("未知错误！创建项目失败！");
    }

}
